package com.yuntian;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baidu.bce.idaas.IDaaSClient;
import com.baidu.bce.idaas.IDaaSClientConfiguration;
import com.baidu.bce.idaas.model.enums.ActorType;
import com.baidu.bce.idaas.model.idaas.IdentityBindingRequest;
import com.baidu.bce.idaas.model.idaas.UserDetail;
import com.baidu.bce.idaas.model.request.OrganizationUnitUserQueryRequest;
import com.baidu.bce.idaas.model.response.PageQueryResponse;
import com.baidu.bce.idaas.utils.SimpleCryptorUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
@EnableScheduling
public class SyncScheduler {

    @Autowired(required = false)
    private RestTemplate restTemplate;


    @Autowired
    private CustomConfig customConfig;

    @Autowired(required = false)
    private IDaaSClientConfiguration iDaaSClientConfiguration;


   /* @Scheduled(cron = "0 0 0/1 * * ?")*/
    public void syncDataTask() {
        log.info("开始同步数据");
        Date now = DateUtil.date();
//        Date startOfYesterday = DateUtil.beginOfDay(DateUtil.offsetDay(now, -1));
//        String formattedDate = DateUtil.format(startOfYesterday, "yyyy-MM-dd HH:mm:ss");
        syncData(null);
        log.info("同步数据完成");
    }

    /**
     * {@inheritDoc}
     * 同步数据，包括组织机构和用户信息。
     *
     * @param searchTime String 搜索时间，格式为yyyy-MM-dd HH:mm:ss
     * @since 2021/9/30
     */
    public void syncData(String searchTime) {
        String authToken = authToken();
        syncOrg(searchTime, CollUtil.newHashSet(), authToken);
        syncUser(searchTime, CollUtil.newHashSet(), authToken);
    }

    /**
     * @Description 同步组织机构数据，分页拉取并处理数据
     * @Param searchTime String - 查询时间，可选参数，格式为yyyy-MM-dd HH:mm:ss
     * @Param finishDataIds List<String> - 已经完成的数据ID列表，用于记录已经处理过的数据
     * @Return void - 无返回值
     * @Throws void - 无异常抛出
     */
    public void syncOrg(String searchTime, Set<String> finishDataIds, String authToken) {
        boolean flag = true;
        while (flag) {
            JSONObject body = new JSONObject();
            if (StrUtil.isNotBlank(searchTime)) {
                body.set("searchTime", searchTime);
            }
            body.set("dataType", "ORG");
            body.set("pageNo", 0);
            body.set("pageSize", 100);
            log.info("syncData ORG body:{}", body);
            JSONArray responseBody = pullData(body, authToken);
            if (ObjUtil.isEmpty(responseBody) || responseBody.size() == 0) {
                log.info("syncData ORG responseBody is empty");
                flag = false;
                break;
            }
            log.info("syncData ORG body:{} flag:{}", body, flag);
            // TODO 推送数据至ab接口
            handleData(responseBody, finishDataIds, "ORG", null);
            log.debug("syncData org finishDataIds:{}", finishDataIds);
            log.info("syncData org finishDataIds.size:{}", finishDataIds.size());
            // 完成数据拉取通知
            if (CollUtil.isNotEmpty(finishDataIds)) {
                JSONObject obj = JSONUtil.createObj();
                JSONArray array = JSONUtil.createArray();
                array.addAll(finishDataIds);
                obj.put("dataIds", array);
                log.debug("syncData org finishDataIds:{}", obj);
                finishData(obj);
            }
        }
    }


    /**
     * @throws Exception 无异常抛出
     * @Description 同步用户信息，包括拉取用户数据和处理数据
     * @Param searchTime String 查询时间，可为空字符串，格式为yyyy-MM-dd HH:mm:ss
     * @Param finishDataIds List<String> 已经完成的数据ID列表，可为空List
     * @Return void 无返回值
     */
    public void syncUser(String searchTime, Set<String> finishDataIds, String authToken) {
        boolean flag = true;
        Map<String, JSONObject> departmentMap = getDepartmentMap("name");
        while (flag) {
            JSONObject body = new JSONObject();
            if (StrUtil.isNotBlank(searchTime)) {
                body.set("searchTime", searchTime);
            }
            body.set("dataType", "ACC");
            body.set("pageNo", 0);
            body.set("pageSize", 100);
            JSONArray responseBody = pullData(body, authToken);
            if (ObjUtil.isEmpty(responseBody) || responseBody.size() == 0) {
                log.info("syncData ACC responseBody is empty");
                flag = false;
                break;
            }
            log.info("syncData ACC body:{} flag:{}", body, flag);
            // TODO 推送数据至ab接口
            handleData(responseBody, finishDataIds, "ACC", departmentMap);
            log.debug("syncData acc finishDataIds:{}", finishDataIds);
            log.info("syncData acc finishDataIds.size:{}", finishDataIds.size());
            // 完成数据拉取通知
            if (CollUtil.isNotEmpty(finishDataIds)) {
                JSONObject obj = JSONUtil.createObj();
                JSONArray array = JSONUtil.createArray();
                array.addAll(finishDataIds);
                obj.put("dataIds", array);
                log.debug("syncData acc finishDataIds:{}", obj);
                finishData(obj);
            }
        }
    }


    /**
     * 授权接口调用token
     *
     * @return
     */
    public String authToken() {
        HashMap<String, Object> params = new HashMap<>();
        params.put("client_id", customConfig.getTaskAuthClientId());
        params.put("client_secret", customConfig.getTaskAuthClientSecret());
        params.put("grant_type", "client_credentials");
        params.put("scope", "basic");
        log.info("authToken params:{}", params);
        String responseStr = HttpUtil.post(customConfig.getTaskAuthTokenPath(), params);
        JSONObject responseJson = JSONUtil.parseObj(responseStr);
        String cacheToken = responseJson.getStr("token_type") + " " + responseJson.getStr("access_token");
        log.info("authToken token:{}", cacheToken);
        return cacheToken;
    }

    /**
     * 拉取数据
     *
     * @param
     * @return
     */
    public JSONArray pullData(JSONObject requestBody, String authToken) {
        log.debug("pullData requestStr:{}", requestBody);
        HttpResponse execute =
                HttpUtil.createPost(customConfig.getTaskPullDataPath())
                        .header(HttpHeaders.AUTHORIZATION, authToken)
                        .body(requestBody.toString())
                        .disableCache()
                        .execute();
        if (execute.isOk()) {
            String responseStr = execute.body();
            log.debug("pullData responseStr:{}", responseStr);
            JSONObject responseBody = JSONUtil.parseObj(responseStr);
            JSONObject data = responseBody.getJSONObject("data");
            JSONArray list = data.getJSONArray("list");
            return list;
        }
        log.error("pull data error authToken:{} requestBody:{} responseBody:{}",
                authToken,
                requestBody,
                execute.body());
        return null;
    }

    /**
     * 完成数据拉取通知
     *
     * @param dataIds
     */
    public void finishData(JSONObject dataIds) {
        HttpResponse execute =
                HttpUtil.createPost(customConfig.getTaskServerPullFinishPath())
                        .auth(authToken()).body(dataIds.toString()).disableCache().execute();
        if (execute.isOk()) {
            String responseStr = execute.body();
            log.info("finishData responseStr:{}", responseStr);
        }
    }

    /**
     * @Description: 处理数据，包括组织和用户的创建、更新和删除操作
     * @Param list JSONArray 需要处理的数据列表，每个元素为一个JSONObject，包含id、parentCode、orgCode、dataJson等属性
     * @Param dataIds List<String> 已经处理完成的数据id列表，用于记录已经处理过的数据id
     * @Param dataType String 数据类型，可选值：ORG（组织）、ACC（用户）
     * @Return void 无返回值
     */
    public void handleData(JSONArray list, Collection<String> dataIds, String dataType,
                           Map<String, JSONObject> departmentMap) {
        log.debug("handleData list:{}", list);
        // TODO 处理数据
        list.stream().forEach((item) -> {
            JSONObject itemJson = (JSONObject) item;
            String id = itemJson.getStr("id");
            log.info("handleData id:{}", id);
            dataIds.add(id);
            String parentCode = replaceSymbol(itemJson.getStr("parentCode"));
            String orgCode = replaceSymbol(itemJson.getStr("orgCode"));
            JSONObject dataInfo = itemJson.getJSONObject("dataJson");
            log.info("handleData id:{} parentCode:{} orgCode:{}", id, parentCode, orgCode);
            log.debug("handleData id:{} parentCode:{} orgCode:{} dataInfo:{}", id, parentCode, orgCode, dataInfo);
            if (ObjUtil.isEmpty(dataInfo)) {
                log.error("handleData dataInfo is null id:{}", id);
                return;
            }
            JSONObject data = dataInfo.getJSONObject("data");
            Boolean isDisabled = data.getBool("isDisabled");
            if (ObjUtil.isNotEmpty(isDisabled) && isDisabled) {
                log.debug("handleData isDisabled:{} id:{}", isDisabled, id);
                dataIds.add(id);
                return;
            }
            log.debug("handleData data:{}", data);
            if (ObjUtil.isEmpty(data)) {
                log.error("handleData data is null id:{}", id);
                return;
            }
            String effectOn = dataInfo.getStr("effectOn");
            String organization = replaceSymbol(data.getStr("_organization"));
            List<String> organizationList = Arrays.asList(organization.split("/"));
            log.info("handleData effectOn:{} organization:{} organizationList:{}", effectOn, organization,
                    organizationList);
            if (StrUtil.equals(dataType, "ORG")) {
                if (!StrUtil.equals(organizationList.get(0), "深圳市水务_集团_有限公司")) {
                    return;
                }
                String name = replaceSymbol(data.getStr("name"));
                String code = data.getStr("code");
                // description存储当前组织的全路径 + 当前组织的code
                // 查找父节点时通过description字段，parent计算出父节点的全路径，再通过description字段查找父节点
                // 父节点的description = 父节点的全路径 + 父节点的code
                List<String> parent = organizationList.stream()
                        .limit(organizationList.size() - 1)
                        .collect(Collectors.toList());
                log.info("handleData name:{} code:{} parent:{}", name, code, parent);
                if (StrUtil.equals("CREATED", effectOn)) {
                    JSONObject addObj = JSONUtil.createObj();
                    addObj.set("name", name + "_" + code);
                    // 策略打平节点，只保留前5层
                    extracted(parentCode, organization, name, code, parent, addObj);
                    if (!JSONUtil.isNull(addObj)) {
                        JSONObject response = callRemoteAbApi(customConfig.getAbDataDepartmentAddUrl(), addObj);
                        log.info("handleData org addObj:{} response:{}", addObj, response);
                        if (ObjUtil.isNotEmpty(response) && response.getInt("code").equals(0)) {
                            dataIds.add(id);
                        } else {
                            log.error("handleData org add error url:{} parentCode:{} original:{} request:{} " +
                                            "response:{}",
                                    customConfig.getAbDataDepartmentAddUrl(),
                                    parentCode,
                                    itemJson,
                                    addObj,
                                    response);
                        }
                    }
                } else if (StrUtil.equals("UPDATED", effectOn)) {
                    JSONObject updateObj = JSONUtil.createObj();
                    String nameCode = name + "_" + code;
                    String departmentId = getDepartmentByKV("name", nameCode);
                    updateObj.set("name", nameCode);
                    // 策略打平节点，只保留前5层
                    extracted(parentCode, organization, name, code, parent, updateObj);
                    if (!JSONUtil.isNull(updateObj)) {
                        if (StrUtil.isNotBlank(departmentId)) {
                            updateObj.set("department_id", departmentId);
                        }
                        JSONObject response = callRemoteAbApi(customConfig.getAbDataDepartmentUpdateUrl(), updateObj);
                        log.info("handleData org updateObj:{} response:{}", updateObj, response);
                        if (ObjUtil.isNotEmpty(response) && response.getInt("code").equals(0)) {
                            dataIds.add(id);
                        } else {
                            log.error("handleData org update error url:{} parentCode:{} original:{} request:{} " +
                                            "response:{}",
                                    customConfig.getAbDataDepartmentUpdateUrl(),
                                    parentCode,
                                    itemJson,
                                    updateObj,
                                    response);
                        }
                    }
                } else if (StrUtil.equals("DELETED", effectOn)) {
                    JSONObject delObj = JSONUtil.createObj();
                    String departmentId = getDepartmentByKV("name", name + "_" + code);
                    if (StrUtil.isNotBlank(departmentId)) {
                        delObj.set("department_id", departmentId);
                        JSONObject response = callRemoteAbApi(customConfig.getAbDataDepartmentDeleteUrl(), delObj);
                        log.info("handleData org delObj:{} response:{}", delObj, response);
                        if (ObjUtil.isNotEmpty(response) && response.getInt("code").equals(0)) {
                            dataIds.add(id);
                        } else {
                            log.error("handleData org delete error url:{} parentCode:{} original:{} delObj:{} " +
                                            "response:{}",
                                    customConfig.getAbDataDepartmentDeleteUrl(),
                                    parentCode,
                                    itemJson,
                                    delObj,
                                    response);
                        }
                    }
                }
            } else if (StrUtil.equals(dataType, "ACC")) {
                List<String> orgCodeList = StrUtil.split(orgCode, "/");
                if (!StrUtil.equals(orgCodeList.get(0), "深圳市水务_集团_有限公司")) {
                    return;
                }
                // CREATED,UPDATED,DELETED,ENABLED,DISABLED，对象的操作类型。
                String username = data.getStr("username");
                if (StrUtil.equals("CREATED", effectOn)) {
                    JSONObject requestBody = new JSONObject();
                    requestBody.set("description", data.getStr("fullname"));
                    requestBody.set("name", username);
                    requestBody.set("position", "普通员工");
                    // 1.普通用户-user
                    // 2.管理员-admin
                    // 3.开发者-developer
                    requestBody.set("role_name", "user");
                    requestBody.set("mobile", "13322222222"); // 给默认电话
                    requestBody.set("password", customConfig.getAbDataUserDefaultPassword());
                    // TODO 处理组织信息 根据组织名称查询组织id(ab系统)
                    JSONObject department = departmentMap.get(CollUtil.get(orgCodeList, -1));
                    if (ObjUtil.isNotEmpty(department)) {
                        String departmentId = department.getStr("department_id");
                        requestBody.set("department_id", departmentId);
                        JSONObject response = callRemoteAbApi(customConfig.getAbDataUserAddUrl(), requestBody);
                        log.info("handleData CREATED ACC request:{} response:{}", requestBody, response);
                        if (ObjUtil.isNotEmpty(response) && response.getInt("code").equals(0)) {
                            // TODO idaas关系绑定
                            bindingIdaasUser(username);
                            storageTokenByUser(username);
                            dataIds.add(id);
                        } else {
                            log.error("handleData acc add error url:{} orgCode:{} original:{} requestBody:{} " +
                                            "response:{}",
                                    customConfig.getAbDataUserAddUrl(),
                                    orgCode,
                                    itemJson,
                                    requestBody,
                                    response);
                        }
                    }
                } else if (StrUtil.equals("UPDATED", effectOn)) {
                    JSONObject requestBody = new JSONObject();
                    requestBody.set("description", data.getStr("fullname"));
                    requestBody.set("position", "普通员工");
                    requestBody.set("mobile", "13322222222"); // 给默认电话
                    // TODO 查询用户在ab系统的id
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.set("keyword", username);
                    jsonObject.set("page", 1);
                    jsonObject.set("limit", 10);
                    JSONObject oldUser = callRemoteAbApi(customConfig.getAbDataUserQueryUrl(), jsonObject);
                    String accountId = "";
                    if (ObjUtil.isNotEmpty(oldUser)) {
                        JSONObject result = oldUser.getJSONObject("result");
                        if (ObjUtil.isNotEmpty(result)) {
                            JSONObject entries = result.getJSONArray("result")
                                    .stream().map(user -> (JSONObject) user)
                                    .filter(user -> StrUtil.equals(user.getStr("name"), username))
                                    .findFirst()
                                    .orElse(JSONUtil.createObj());
                            if (ObjUtil.isNotEmpty(entries)) {
                                accountId = entries.getStr("account_id");
                            }
                        }
                    }
                    requestBody.set("account_id", accountId);
                    JSONObject response = callRemoteAbApi(customConfig.getAbDataUserUpdateUrl(), requestBody);
                    if (ObjUtil.isNotEmpty(response) && response.getInt("code").equals(0)) {
                        dataIds.add(id);
                    } else {
                        log.error("handleData acc update error url:{} orgCode:{} original:{} requestBody:{} " +
                                        "response:{}",
                                customConfig.getAbDataUserUpdateUrl(),
                                orgCode,
                                itemJson,
                                requestBody,
                                response);
                    }
                } else if (StrUtil.equals("DELETED", effectOn)) {
                    String accountId = "";
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.set("keyword", username);
                    jsonObject.set("page", 1);
                    jsonObject.set("limit", 10);
                    JSONObject oldUser = callRemoteAbApi(customConfig.getAbDataUserQueryUrl(), jsonObject);
                    if (ObjUtil.isNotEmpty(oldUser)) {
                        JSONObject result = oldUser.getJSONObject("result");
                        if (ObjUtil.isNotEmpty(result)) {
                            accountId = result.getJSONArray("result")
                                    .stream().map(user -> (JSONObject) user)
                                    .filter(user -> StrUtil.equals(user.getStr("name"), username))
                                    .findFirst()
                                    .get()
                                    .getStr("account_id");
                        }
                    }
                    JSONObject requestBody = JSONUtil.createObj();
                    JSONArray accountIds = JSONUtil.createArray();
                    accountIds.set(accountId);
                    requestBody.set("account_ids", accountIds);
                    if (CollUtil.isNotEmpty(accountIds)) {
                        JSONObject response = callRemoteAbApi(customConfig.getAbDataUserDeleteUrl(), requestBody);
                        if (ObjUtil.isNotEmpty(response) && response.getInt("code").equals(0)) {
                            dataIds.add(id);
                        } else {
                            log.error("handleData acc delete error url{} orgCode:{} original:{} requestBody:{} " +
                                            "response:{}",
                                    customConfig.getAbDataUserDeleteUrl(),
                                    orgCode,
                                    itemJson,
                                    requestBody,
                                    response);
                        }
                    }
                }
            }
        });
        log.info("handleData list.size:{}", list.size());
    }


   /* public Map<String, JSONObject> getDepartmentMap(String mapKey) {
        JSONObject entries1 = callRemoteAbApi(customConfig.getAbDataDepartmentQueryUrl(),
                JSONUtil.createObj());
        LinkedHashMap<String, JSONObject> buildDepartmentMap =
                DepartmentTraverser.buildDepartmentMap(entries1.getJSONArray("result"), mapKey);
        log.info("buildDepartmentMap.size:{}", buildDepartmentMap.size());
        return buildDepartmentMap;
    }*/

    public Map<String, JSONObject> getDepartmentMap(String mapKey) {
        return null;
    }


    /**
     * 组织数据映射处理
     *
     * @param parentCode
     * @param organization
     * @param name
     * @param code
     * @param parent
     * @param jsonObject
     */
    private void extracted(String parentCode,
                           String organization,
                           String name,
                           String code,
                           List<String> parent,
                           JSONObject jsonObject) {
        log.debug("extracted parentCode:{} organization:{} name:{} code:{} parent:{}",
                parentCode, organization, name, code, parent);
        String description = organization + "_" + code;
        if (CollUtil.isEmpty(parent)) {
            jsonObject.set("parent_department_id", null);
        } else if (parent.size() == 1) {
            jsonObject.set("description", description);
            jsonObject.set("parent_department_id", customConfig.getAbDataDefaultParentDepartmentId());
        } else {
            String parentDepartmentId = null;
            // TODO 第五层级开始需要打平
            if (parent.size() >= 5) {
                log.debug("extracted parent:{}", parent);
                // 去除水务集团节点
                List<String> duplicate = CollUtil.newArrayList(parent);
                parent = parent.stream()
                        .limit(4)
                        .collect(Collectors.toList());
                parentDepartmentId = getDepartmentByKV("description", StrUtil.join("/", parent));
                duplicate.add(name);
                description = StrUtil.join("/", duplicate) + "_" + code;
            }
            if (StrUtil.isBlank(parentDepartmentId)) {
                parentDepartmentId = getDepartmentByKV("description", StrUtil.join("/", parent));
            }
            jsonObject.set("description", description);
            jsonObject.set("parent_department_id", parentDepartmentId);
        }
        // 找不到上级id则不操作
        if (StrUtil.isBlank(jsonObject.getStr("parent_department_id"))) {
            jsonObject = null;
        }
        log.debug("extracted jsonObject:{}", jsonObject);
    }

    /**
     * 调用远程ab接口
     *
     * @param url
     * @param requestBody
     * @return
     */
    public JSONObject callRemoteAbApi(String url, JSONObject requestBody) {
        HttpResponse execute = HttpUtil.createPost(url)
                .header(Header.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .header("Authorization", "Bearer " + customConfig.getAbDataKey())
                .header("X-Authorization", "Bearer " + customConfig.getAbDataKey())
                .body(requestBody.toString())
                .disableCache().execute();
        log.debug("callRemoteAbApi url:{} requestBody:{} response:{}", url, requestBody, execute.body());
        if (execute.isOk()) {
            String body = execute.body();
            return JSONUtil.parseObj(body);
        } else {
            log.error("callRemoteAbApi error url:{} requestBody:{} response:{}", url, requestBody, execute.body());
        }
        return null;
    }

    /**
     * idaas关系绑定
     *
     * @param username
     */
    public void bindingIdaasUser(String username) {
        log.info("开始绑定idaas用户:{}", username);
        IdentityBindingRequest request = new IdentityBindingRequest();
        // idaas配置取
        request.setProjectId(customConfig.getIdaasProjectId());
        request.setTargetProviderId(customConfig.getIdaasJwtTargetProviderId());
        request.setTargetType("PROVIDER");
        OrganizationUnitUserQueryRequest queryRequest = new OrganizationUnitUserQueryRequest();
        queryRequest.setProjectId(customConfig.getIdaasProjectId());
        queryRequest.setPageNo(1);
        queryRequest.setPageSize(1);
        queryRequest.setKeywordType(1);
        queryRequest.setKeyword(username);
        queryRequest.setStatus(null);
        log.info("bindingIdaasUser queryRequest:{}", queryRequest);
        IDaaSClient iDaaSClient = new IDaaSClient(iDaaSClientConfiguration);
        PageQueryResponse<UserDetail> userDetailPageQueryResponse = iDaaSClient.userList(queryRequest);
        Collection<UserDetail> result = userDetailPageQueryResponse.getPage().getResult();
        if (CollUtil.isEmpty(result)) {
            log.error("bindingIdaasUser userDetail is null username:{}", username);
            return;
        }
        log.info("bindingIdaasUser result.size:{}", result.size());
        log.info("bindingIdaasUser userDetail:{}", result);
        UserDetail userDetail = result.stream().findFirst().orElse(null);
        request.setActorId(userDetail.getId());
        request.setActorType(ActorType.USER.name());
        // ab系统用户id
        request.setTargetActorId(username);
        request.setTargetActorType("SUBUSER");
        request.setStatus(1);
        log.info("idaas binding user param:{}", request);
        try {
            iDaaSClient.updateIdentityBinding(request);
        } catch (Exception e) {
            log.error("bindingIdaasUser error username:{} error:{}", username, e.getMessage());
        }
        iDaaSClient.shutdown();
    }


//    public static void main(String[] args) {
//        String deparment = "深圳市水务_集团_有限公司/二级企业/深圳市环水投资集团有限公司/池州市深水水务有限公司/区域审计中心_b1657";
//        String json = FileUtil.readString("/Users/v_wangxuecai/Desktop/shard" +
//                        "_code/baidu/det-drd-gov/prj-shenzhen-sw-sso/src/main/resources/1.json",
//                "UTF-8");
//
//        List<String> collect = StrUtil.split(deparment, "/").stream().limit(4).collect(Collectors.toList());
//        JSONObject entries = JSONUtil.parseObj(json);
//        JSONArray result = entries.getJSONArray("result");
//        List<JSONObject> jsonObjects = filterNodesByName(result, "description", StrUtil.join("/", collect));
//        String departmentId = null;
//        if (CollUtil.isNotEmpty(jsonObjects) && jsonObjects.size() > 0) {
//            departmentId = jsonObjects.get(0).getStr("department_id");
//        }
//        System.out.println("department_id     " + departmentId);
//    }

    /**
     * 根据key和value查询部门id
     *
     * @param key   AB组织数据中返回的字段，如name,code等
     * @param value AB组织数据中返回的字段值，如name,code等
     * @return
     */
    public String getDepartmentByKV(String key, String value) {
        log.info("getDepartmentByKV key:{} value:{}", key, value);
        String departmentId = "";
        JSONObject departmentList = callRemoteAbApi(customConfig.getAbDataDepartmentQueryUrl(),
                JSONUtil.createObj());
        if (ObjUtil.isNotEmpty(departmentList)) {
            JSONArray result = departmentList.getJSONArray("result");
            // 优先使用第一位
            List<JSONObject> jsonObjects = filterNodesByName(result, key, value);
            if (CollUtil.isNotEmpty(jsonObjects) && jsonObjects.size() > 0) {
                departmentId = jsonObjects.get(0).getStr("department_id");
            }
        }
        log.info("getDepartmentByKV departmentId:{}", departmentId);
        return departmentId;
    }


    /**
     * @Description 根据名称过滤JSON数组中的节点，返回符合条件的节点列表
     * @Param jsonArray JSONArray 需要过滤的JSON数组，包含节点信息
     * @Param key String 节点信息中用于过滤的属性名，例如"name"
     * @Param value String 需要匹配的值，例如"张三"
     * @Return List<JSONObject> 符合条件的节点列表，JSONObject格式为{"id":1,"name":"张三"}
     * @See org.json.JSONArray#getJSONArray(String)
     * @See org.json.JSONArray#isEmpty()
     */
    public static List<JSONObject> filterNodesByName(JSONArray jsonArray, String key, String value) {
        log.debug("filterNodesByName jsonArray:{} key:{} value:{}", jsonArray, key, value);
        List<JSONObject> result = new ArrayList<>();
        if (jsonArray == null) {
            return result;
        }
        for (Object obj : jsonArray) {
            JSONObject node = (JSONObject) obj;
            // 检查当前节点是否匹配
            String nodeValueByKey = node.getStr(key);
            if (StrUtil.equals("description", key)) {
                nodeValueByKey = StrUtil.sub(nodeValueByKey,
                        0,
                        StrUtil.lastIndexOf(nodeValueByKey,
                                "_",
                                nodeValueByKey.length(),
                                false));
            }
            if (value.equals(nodeValueByKey)) {
                result.add(node);
            }
            // 递归处理子节点
            JSONArray children = node.getJSONArray("children");
            if (children != null && !children.isEmpty()) {
                result.addAll(filterNodesByName(children, key, value));
            }
        }
        log.debug("filterNodesByName result:{}", result);
        return result;
    }

    /**
     * @param username 用户名
     * @return void
     * @throws Exception 无
     * @Description: 根据用户名存储token，并将其保存到文件中
     */
    public void storageTokenByUser(String username) {
        String token = loginGetToken(username);
        JSONObject storageToken = new JSONObject();
        storageToken.set(username, token);
        log.info("storageTokenByUser username:{} token:{}", username, token);
        // 追加到文件中
        appendToJsonArray(customConfig.getAbDataStorageTokenUrl(), storageToken);
    }

    /**
     * @param filePath  文件路径
     * @param newObject 需要追加的JSON对象
     * @throws Exception 可能会抛出IOException、ParseException等异常
     * @Description 将一个JSON对象追加到指定的JSON数组中，并保存到文件中。
     */
    public static void appendToJsonArray(String filePath, JSONObject newObject) {
        try {
            // 读取文件内容
            if (!FileUtil.exist(filePath)) {
                FileUtil.touch(filePath);
            }
            String jsonStr = FileUtil.readString(filePath, StandardCharsets.UTF_8);

            // 解析JSON（处理空文件情况）
            JSONArray jsonArray = jsonStr.isEmpty() ? new JSONArray() : JSONUtil.parseArray(jsonStr);

            // 添加新对象
            jsonArray.add(newObject);

            // 写回文件（格式化输出）
            FileUtil.writeString(JSONUtil.toJsonPrettyStr(jsonArray),
                    filePath,
                    StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("处理JSON文件时出错: " + e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * 根据新用户 模拟登录拿到Cookie 然后 拿到Token
     *
     * @param username
     * @return
     */
    public String loginGetToken(String username) {
        log.info("loginGetToken username:{}", username);
        String token = StrUtil.EMPTY;
        // 密码加密 使用到了密钥调用登录接口 模拟登录。 然后 添加 调用 token add
        String passwordEncryption = Base64.getEncoder().encodeToString(
                SimpleCryptorUtils.rsaEncrypt(customConfig.getAbDataUserDefaultPassword(), getPublicKey()));
        String cookie = abLogin(username, passwordEncryption);
        String result = HttpUtil.createPost(customConfig.getAbDataAddTokenUrl())
                .cookie(cookie)
                .body(StrUtil.EMPTY_JSON)
                .execute()
                .body();
        JSONObject jsonObject = JSONUtil.parseObj(result);
        if (jsonObject.getInt("code") == 0) {
            token = jsonObject.getJSONObject("result").getStr("token", StrUtil.EMPTY);
            log.info("用户:{},成功从ab系统 获取到Token:{}", username, token.substring(0, 8));
        } else {
            log.error("用户:{},获取Token失败.", username);
        }
        return token;
    }

    /**
     * @return String 返回一个字符串类型的公钥，如果获取失败则返回空字符串
     * @Description 获取公钥，返回字符串类型的公钥
     */
    public String getPublicKey() {
        String res = HttpUtil.get(customConfig.getAbLoginPublicKey());
        JSONObject jsonObject = JSONUtil.parseObj(res);
        JSONObject resultJsonobject = jsonObject.getJSONObject("result");
        Integer status = jsonObject.getInt("status");
        Boolean success = jsonObject.getBool("success");
        String publicKeyCert = resultJsonobject.getStr("publicKeyCert");
        if (status.compareTo(200) == 0 && success) {
            log.info("从ab加载公钥成功 publicKeyCert:{}", publicKeyCert);
            return publicKeyCert;
        }
        return StrUtil.EMPTY;
    }

    /**
     * @Description 登录AB系统，返回cookie字符串
     * @Param username 用户名
     * @Param passwordEncryption 密码加密后的字符串（不需要传入）
     * @Return java.lang.String 返回cookie字符串，格式如：cookie1;cookie2;...
     * @Throws Exception 无
     */
    public String abLogin(String username, String passwordEncryption) {
        JSONObject requestBody = new JSONObject();
        requestBody.set("username", username);
        requestBody.set("password", "EzadjtR1nAV9DZ/OX8QbvrnQzOJ6RZWwl/jcyA" +
                "+kjBYYCrvvOkLYx3jHBY4jsBwu3GRZNTBIZissu281rijM5LXl7Z841X9sjGc2aOsz" +
                "Wujnqc5vETFXCKP1HN5j7gJ9CzFxAJFBzxpapeTuHJ09Sp+eVsPKewUpusGCUtB8MT0sz" +
                "CaBttm3zF2Khp6zU3S9GFSbwbwhALwpiFRmJTlo+QPLkGa9xs1jRRHemqzl3OmNFSdJCm+" +
                "/TtGNLUrd+WjAIFMjoI7dUaNygt/Yk3hVqVO39Di13BDrezZ/K2PUQL3Pddd6qoIYLMza4V5a" +
                "4eiFdRzHNnGQhvbG7nNDnfFwBQ==");
//        requestBody.set("password", passwordEncryption);

        requestBody.set("captchaKey", StrUtil.EMPTY);
        log.debug("abLogin requestBody:{}", requestBody);
        // 请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        // 封装请求实体
        HttpEntity<String> requestEntity = new HttpEntity<>(requestBody.toString(), headers);
        ResponseEntity<String> exchange = restTemplate.exchange(
                customConfig.getAbLoginUrl(),
                HttpMethod.POST,
                requestEntity,
                String.class
        );
        log.debug("abLogin response:{}", exchange.getBody());
        List<String> cookieList = exchange.getHeaders().get("Set-Cookie");
        if (CollUtil.isEmpty(cookieList)) {
            log.error("登录ab系统获取cookie为空,会影响后续使用,请检查!");
        }
        return CollUtil.join(cookieList, ";");
    }

    /**
     * 替换符号，将中文全角标点和英文半角逗号替换为下划线，并去除中文全角括号。
     *
     * @param text 需要替换的字符串
     * @return 返回替换后的字符串，中文全角标点和英文半角逗号替换为下划线，中文全角括号去除
     */
    public String replaceSymbol(String text) {
        log.info("replaceSymbol text:{}", text);
        if (StrUtil.isNotBlank(text)) {
            String replace = text.replace("(", "_")
                    .replace(")", "_")
                    .replace("（", "_")
                    .replace("）", "_")
                    .replace("、", "_")
                    .replace("-", "_");
            log.debug("replaceSymbol replace:{}", replace);
            return replace;
        }
        return text;
    }

    /**
     * 测试方法，用于调试日志输出
     *
     * @return void 无返回值
     */
    public void test() {
        log.debug("123");
    }

}
